package com.betting.controller;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.betting.dto.StreakStats;
import com.betting.entity.BetRecord;
import com.betting.entity.BetResult;
import com.betting.service.BetRecordService;
import com.betting.dto.BetRecordDTO;
import lombok.RequiredArgsConstructor;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import javax.validation.Valid;
import java.time.LocalDate;
import java.util.Map;
import java.util.List;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.time.format.DateTimeFormatter;
import java.time.LocalDateTime;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import lombok.extern.slf4j.Slf4j;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.stream.Collectors;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import java.time.LocalTime;
import com.betting.dto.DailyProfitDTO;
import com.betting.dto.WeeklyProfitDTO;
import java.util.HashMap;


@Slf4j
@Controller
@RequestMapping("/bet")
@RequiredArgsConstructor
public class BetRecordController {

    private final BetRecordService betRecordService;

    @GetMapping("/list")
    public String list(
            @RequestParam(defaultValue = "1") @Min(1) Integer pageNum,
            @RequestParam(defaultValue = "10") @Min(1) @Max(100) Integer pageSize,
            Model model) {
        
        // 构建查询条件：只查询未结算的记录
        LambdaQueryWrapper<BetRecord> queryWrapper = new LambdaQueryWrapper<BetRecord>()
            .and(wrapper -> wrapper
                .isNull(BetRecord::getBetResult)  // betResult 为 null
                .or()
                .eq(BetRecord::getBetResult, "")  // 或 betResult 为空字符串
            )
            .orderByAsc(BetRecord::getBetTime);  // 按时间正序排序
        
        Page<BetRecord> page = betRecordService.getRecordsByPage(
            new Page<>(pageNum, pageSize),
            queryWrapper
        );
        
        // 格式化日期
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
        page.getRecords().forEach(record -> {
            if (record.getBetTime() != null) {
                record.setBetTimeStr(record.getBetTime().format(formatter));
            }
        });
        
        model.addAttribute("page", page);
        return "bet/list";
    }

    @GetMapping("/add")
    public String addForm(Model model) {
        model.addAttribute("record", new BetRecordDTO());
        return "bet/add";
    }

    @PostMapping("/add")
    public String add(@Valid BetRecordDTO betRecordDTO, 
                      BindingResult result,
                      RedirectAttributes redirectAttributes) {
        try {
            // 记录接收到的数据
            log.info("Received bet record data: {}", betRecordDTO);
            
            // 检查验证错误
            if (result.hasErrors()) {
                log.error("Validation errors: {}", result.getAllErrors());
                redirectAttributes.addFlashAttribute("error", "表单数据验证失败：" + result.getAllErrors());
                return "redirect:/bet/add";
            }
            
            // 转换并保存记录
            BetRecord record = convertToEntity(betRecordDTO);
            log.info("Converting to entity: {}", record);
            
            betRecordService.saveRecord(record);
            log.info("Record saved successfully: {}", record);
            
            redirectAttributes.addFlashAttribute("message", "投注记录添加成功");
            return "redirect:/bet/list";
        } catch (Exception e) {
            log.error("Error adding bet record: {}", e.getMessage(), e);
            redirectAttributes.addFlashAttribute("error", "添加失败：" + e.getMessage());
            return "redirect:/bet/add";
        }
    }

    @GetMapping("/edit/{id}")
    public String editForm(@PathVariable Long id, Model model) {
        BetRecord record = betRecordService.getRecordById(id);
        if (record == null) {
            throw new RuntimeException("记录不存在");
        }
        // 格式化日期
        if (record.getBetTime() != null) {
            record.setBetTimeStr(record.getBetTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm")));
        }
        model.addAttribute("record", convertToDTO(record));
        return "bet/edit";
    }

    @PostMapping("/edit")
    public String edit(@Valid BetRecordDTO recordDTO,
                      BindingResult result,
                      Model model,
                      RedirectAttributes redirectAttributes) {
        if (result.hasErrors()) {
            model.addAttribute("record", recordDTO);
            return "bet/edit";
        }
        
        try {
            BetRecord record = convertToEntity(recordDTO);
            betRecordService.updateById(record);
            redirectAttributes.addFlashAttribute("message", "更新成功");
            return "redirect:/bet/list";
        } catch (Exception e) {
            log.error("更新失败: {}", e.getMessage(), e);
            model.addAttribute("record", recordDTO);
            model.addAttribute("error", "更新失败：" + e.getMessage());
            return "bet/edit";
        }
    }

    @GetMapping("/delete/{id}")
    public String delete(@PathVariable Long id, RedirectAttributes redirectAttributes) {
        try {
            BetRecord record = betRecordService.getRecordById(id);
            if (record == null) {
                redirectAttributes.addFlashAttribute("error", "记录不存在");
                return "redirect:/bet/list";
            }
            betRecordService.deleteRecord(id);
            redirectAttributes.addFlashAttribute("message", "删除成功");
        } catch (Exception e) {
            redirectAttributes.addFlashAttribute("error", "删除失败：" + e.getMessage());
        }
        return "redirect:/bet/list";
    }

    @GetMapping("/daily")
    public String dailySummary(
            @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate date,
            Model model) {
        if (date == null) {
            date = LocalDate.now();
        }
        Map<String, Object> summary = betRecordService.getDailySummary(date);
        model.addAttribute("summary", summary);
        model.addAttribute("date", date);
        return "bet/daily";
    }

    @GetMapping("/weekly")
    public String weeklySummary(
            @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate date,
            Model model) {
        if (date == null) {
            date = LocalDate.now();
        }
        Map<String, Object> summary = betRecordService.getWeeklySummary(date);
        model.addAttribute("summary", summary);
        model.addAttribute("date", date);
        return "bet/weekly";
    }

    @GetMapping("/monthly")
    public String monthlySummary(
            @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate date,
            Model model) throws JsonProcessingException {
        if (date == null) {
            date = LocalDate.now();
        }
        
        Map<String, Object> summary = betRecordService.getMonthlySummary(date, LocalDate.now());
        
        // 获取最近6个月的数据
        List<String> dates = new ArrayList<>();
        List<BigDecimal> profits = new ArrayList<>();
        LocalDate startDate = date.minusMonths(5);
        
        ObjectMapper objectMapper = new ObjectMapper();
        
        for (int i = 0; i < 6; i++) {
            LocalDate currentDate = startDate.plusMonths(i);
            Map<String, Object> monthlySummary = betRecordService.getMonthlySummary(currentDate, LocalDate.now());
            dates.add(currentDate.format(DateTimeFormatter.ofPattern("yyyy-MM")));
            profits.add((BigDecimal) monthlySummary.get("netProfit"));
        }
        
        // 将数据转换为JSON字符串
        model.addAttribute("dates", objectMapper.writeValueAsString(dates));
        model.addAttribute("profits", objectMapper.writeValueAsString(profits));
        model.addAttribute("summary", summary);
        model.addAttribute("date", date);
        
        return "bet/monthly";
    }

    @GetMapping("/settle/{id}")
    public String settleForm(@PathVariable Long id, Model model) {
        BetRecord record = betRecordService.getRecordById(id);
        if (record == null) {
            throw new RuntimeException("记录不存在");
        }
        // 格式化日期
        if (record.getBetTime() != null) {
            record.setBetTimeStr(record.getBetTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm")));
        }
        model.addAttribute("record", convertToDTO(record));
        return "bet/settle";
    }

    @PostMapping("/settle")
    public String settle(@Valid BetRecordDTO recordDTO,
                        BindingResult result,
                        RedirectAttributes redirectAttributes,
                        Model model) {
        try {
            BetRecord record = betRecordService.getRecordById(recordDTO.getId());
            if (record == null) {
                throw new RuntimeException("记录不存在");
            }
            
            // 创建更新对象，只包含需要更新的字段
            BetRecord updateRecord = new BetRecord();
            updateRecord.setId(record.getId());
            updateRecord.setBetResult(String.valueOf(BetResult.valueOf(recordDTO.getBetResult())));
            updateRecord.setResultAmount(recordDTO.getResultAmount());
            updateRecord.setHomeScore(recordDTO.getHomeScore());
            updateRecord.setAwayScore(recordDTO.getAwayScore());
            
            // 调用服务层更新
            betRecordService.updateById(updateRecord);
            
            redirectAttributes.addFlashAttribute("message", "结算成功");
            return "redirect:/bet/list";
        } catch (Exception e) {
            log.error("结算失败: {}", e.getMessage(), e);
            BetRecord record = betRecordService.getRecordById(recordDTO.getId());
            if (record != null) {
                model.addAttribute("record", convertToDTO(record));
            }
            result.rejectValue("", "error.record", "结算失败：" + e.getMessage());
            return "bet/settle";
        }
    }

    @GetMapping("/stats")
    public String stats(
            @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate startDate,
            @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate endDate,
            Model model) throws JsonProcessingException {
        
        // 默认查询最近3个月
        if (startDate == null) {
            startDate = LocalDate.now().minusMonths(2).withDayOfMonth(1);
        }
        if (endDate == null) {
            endDate = LocalDate.now();
        }

        // 获取统计数据
        Map<String, Object> stats = betRecordService.getStatistics(startDate, endDate);
        
        // 使用 ObjectMapper 将数据转换为 JSON 字符串
        ObjectMapper objectMapper = new ObjectMapper();
        model.addAttribute("dailyProfitDates", 
            objectMapper.writeValueAsString(stats.get("dailyProfitDates")));
        model.addAttribute("dailyProfitValues", 
            objectMapper.writeValueAsString(stats.get("dailyProfitValues")));
        model.addAttribute("resultDistribution", 
            objectMapper.writeValueAsString(stats.get("resultDistribution")));
        
        // 添加其他统计数据
        model.addAttribute("stats", stats);
        model.addAttribute("startDate", startDate);
        model.addAttribute("endDate", endDate);

        return "bet/stats";
    }

    @GetMapping("/streak")
    public String streak(
            @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate startDate,
            @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate endDate,
            Model model) {
        if (startDate == null) {
            startDate = LocalDate.now().minusMonths(1);
        }
        if (endDate == null) {
            endDate = LocalDate.now();
        }
        
        StreakStats stats = betRecordService.getStreakStats(startDate, endDate);
        
        // Convert StreakStats to Map for the view
        Map<String, Object> statsMap = new HashMap<>();
        statsMap.put("maxWinStreak", stats.getMaxWinStreak());
        statsMap.put("maxLoseStreak", stats.getMaxLoseStreak());
        statsMap.put("hitRate", stats.getHitRate());
        statsMap.put("streakDetails", stats.getStreakDetails());
        
        model.addAttribute("stats", statsMap);
        model.addAttribute("startDate", startDate);
        model.addAttribute("endDate", endDate);
        return "bet/streak";
    }

    @ExceptionHandler(Exception.class)
    public String handleException(Exception e, Model model) {
        log.error("Error in stats page: ", e);
        model.addAttribute("error", e.getMessage());
        return "error";  // 确保有error.jsp页面
    }

    @GetMapping("/betting")
    public String home() {
        return "index"; // 假设您有一个index.jsp作为首页
    }

    // 转换方法
    private BetRecord convertToEntity(BetRecordDTO dto) {
        if (dto == null) {
            throw new IllegalArgumentException("DTO cannot be null");
        }
        
        BetRecord record = new BetRecord();
        record.setId(dto.getId());
        record.setBetTime(dto.getBetTime() != null ? dto.getBetTime() : LocalDateTime.now());
        record.setHomeTeam(dto.getHomeTeam());
        record.setAwayTeam(dto.getAwayTeam());
        record.setLeagueName(dto.getLeagueName());
        record.setBetType(dto.getBetType());
        record.setHandicapTeam(dto.getHandicapTeam());
        record.setHandicapValue(dto.getHandicapValue() != null ? dto.getHandicapValue() : "0");
        record.setOdds(dto.getOdds() != null ? dto.getOdds() : BigDecimal.ONE);
        record.setBetAmount(dto.getBetAmount() != null ? dto.getBetAmount() : BigDecimal.ZERO);
        record.setResultAmount(dto.getResultAmount() != null ? dto.getResultAmount() : BigDecimal.ZERO);
        record.setHomeScore(dto.getHomeScore());
        record.setAwayScore(dto.getAwayScore());
        record.setNote(dto.getNote());
        
        // Convert String to BetResult enum
        if (dto.getBetResult() != null && !dto.getBetResult().isEmpty()) {
            record.setBetResult(dto.getBetResult());
        } else {
            record.setBetResult(null);  // 设置空值为null
        }
        
        return record;
    }

    private BetRecordDTO convertToDTO(BetRecord entity) {
        if (entity == null) {
            throw new IllegalArgumentException("Entity cannot be null");
        }
        
        BetRecordDTO dto = new BetRecordDTO();
        dto.setId(entity.getId());
        dto.setBetTime(entity.getBetTime());
        dto.setHomeTeam(entity.getHomeTeam());
        dto.setAwayTeam(entity.getAwayTeam());
        dto.setLeagueName(entity.getLeagueName());
        dto.setBetType(entity.getBetType());
        dto.setHandicapTeam(entity.getHandicapTeam());
        dto.setHandicapValue(entity.getHandicapValue());
        dto.setOdds(entity.getOdds());
        dto.setBetAmount(entity.getBetAmount());
        dto.setResultAmount(entity.getResultAmount());
        dto.setHomeScore(entity.getHomeScore());
        dto.setAwayScore(entity.getAwayScore());
        dto.setNote(entity.getNote());
        
        // Convert BetResult enum to String
        if (entity.getBetResult() != null) {
            dto.setBetResult(entity.getBetResult().toString());
        }
        
        return dto;
    }
} 